package com.niiwoo.civet.trade.service.local.newRefund.refundDeal.core;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.niiwoo.activity.stage.enums.prize.UserPrizeTypeIdEnum;
import com.niiwoo.civet.base.enums.OrderTradeSourceEnum;
import com.niiwoo.civet.base.enums.RefundOrderStatusEnum;
import com.niiwoo.civet.trade.dao.entity.*;
import com.niiwoo.civet.trade.dao.mapper.*;
import com.niiwoo.civet.trade.dto.request.RefundWithholdRequestDTO;
import com.niiwoo.civet.trade.enums.*;
import com.niiwoo.civet.trade.service.local.newRefund.common.RefundCommonService;
import com.niiwoo.civet.trade.service.local.newRefund.notify.RefundNotifyFacade;
import com.niiwoo.civet.trade.service.local.newRefund.notify.dto.RefundNotifyDTO;
import com.niiwoo.civet.trade.service.local.newRefund.notify.dto.RefundNotifyMsgDTO;
import com.niiwoo.civet.trade.service.local.newRefund.notify.enums.RefundNotifyEnum;
import com.niiwoo.civet.trade.service.local.newRefund.notify.enums.RefundNotifyHandleStatusEnum;
import com.niiwoo.civet.trade.service.local.newRefund.notify.enums.RefundNotifyRefundSourceEnum;
import com.niiwoo.civet.trade.service.local.newRefund.notify.enums.RefundNotifyRefundStatusEnum;
import com.niiwoo.tripod.lanmao.enums.BusinessTypeEnum;
import com.niiwoo.tripod.provider.exception.BizException;
import com.niiwoo.tripod.service.component.SnowflakeIdWorker;
import lombok.extern.slf4j.Slf4j;
import net.logstash.logback.encoder.org.apache.commons.lang.StringUtils;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronizationAdapter;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CompletableFuture;

/**
 * 还款消息本地服务
 *  
 * @author: kevin.jia
 * @version 1.0.0
 */
@Slf4j
@Service
public class RefundNotifyRecordHandleService {
	
	@Autowired
	private ProjectMapperExt projectMapper;
	
	@Autowired
	private ProjectInvestOrderMapperExt projectInvestOrderMapper;
	
	@Autowired
	private RefundNotifyRecordMapperExt refundNotifyRecordMapper;
	
	@Autowired
	private RefundOrderMapperExt refundOrderMapper;

	@Autowired
	private RefundWithholdOrderMapperExt refundWithholdOrderMapper;
	
	@Autowired
	private ProjectPackageDetailMapperExt projectPackageDetailMapperExt;
	
	@Autowired
	private ProjectPackageMapperExt projectPackageMapperExt;
	
	@Autowired
	private RefundNotifyFacade refundNotifyFacade;	
	
    @Autowired
    private SnowflakeIdWorker snowflakeIdWorker;
    
    @Autowired
    private RefundCommonService refundCommonService;
    
    /**
     * 还款消息处理入口
     * 
     * @param refundNotifyMsgDTO
     */
	@Transactional(isolation = Isolation.READ_COMMITTED)
    public void handleNotify(RefundNotifyMsgDTO refundNotifyMsgDTO) {
    	RefundNotifyDTO refundNotifyDTO = new RefundNotifyDTO(); 

    	if (null == refundNotifyMsgDTO.getProjectId() || refundNotifyMsgDTO.getProjectId() <= 0) {
			throw new BizException("", "还款消息通知异常，必要参数ProjectId为空");
		}
    	
    	refundNotifyDTO.setProjectId(refundNotifyMsgDTO.getProjectId());
    	refundNotifyDTO.setRefundOrderId(refundNotifyMsgDTO.getRefundOrderId());
    	
		// 标的信息
		refundNotifyDTO.setProject(projectMapper.selectByPrimaryKey(refundNotifyDTO.getProjectId()));
		
		// 还款订单
		if (null != refundNotifyMsgDTO.getRefundOrderId() && refundNotifyMsgDTO.getRefundOrderId() > 0) {
			refundNotifyDTO.setRefundOrder(refundOrderMapper.selectByPrimaryKey(refundNotifyDTO.getRefundOrderId()));
		}
		
		// 还款订单业务详情
		if (null != refundNotifyDTO.getRefundOrder() && RefundOrderStatusEnum.HANDLED.getCode().equals(refundNotifyDTO.getRefundOrder().getStatus())) {
			refundNotifyDTO.setRefundOrderDetailBizList(refundCommonService.getNotRefundOrderDetailBizByRefundOrderId(refundNotifyDTO.getRefundOrderId()));
		}
		
		// 变更前状态
		if (null == refundNotifyMsgDTO.getFromSubStatus()) {
			refundNotifyMsgDTO.setFromSubStatus(refundNotifyDTO.getProject().getSubStatus());
		}
		
		// 还款来源
		RefundNotifyRefundSourceEnum refundNotifyRefundSourceEnum = transformRefundSource4WithholdAndRefund(refundNotifyMsgDTO.getWithholdTradeSource(),
				refundNotifyMsgDTO.getRefundTradeSource(), refundNotifyDTO.getRefundOrder());
		
		// 生成还款通知列表，并设置还款消息批次号
		String batchNo = createRefundNotifyRecord(refundNotifyDTO, refundNotifyMsgDTO.getRefundStatus(),
				refundNotifyRefundSourceEnum.getCode(), refundNotifyMsgDTO.getCurrentPeriod(),
				refundNotifyMsgDTO.getFromSubStatus(), refundNotifyDTO.getProject().getSubStatus(),
				refundCommonService.isProjectHirstoryOverdue(refundNotifyDTO.getProject().getBorrowUserId(), refundNotifyDTO.getProject().getProjectId()),
				refundNotifyMsgDTO.getOrgRequestNo(), refundNotifyMsgDTO.getFailMessage());
		
		// 还款批次为空，不做处理
		if (StringUtils.isEmpty(batchNo)) {
			log.info("还款消息处理流程结束，本次需要发送的还款消息列表为空。MQ消息内容：" + JSONObject.toJSONString(refundNotifyMsgDTO));
			return;
		}
		
		refundNotifyDTO.setBatchNo(batchNo);
		log.info("还款消息处理流程，异步调用消息门面统一处理，BatchNo:{}", batchNo);
		
		// 通知入库后，异常发起消息通知处理
		TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
			@Override
			public void afterCommit() {
				super.afterCommit();
				CompletableFuture.runAsync(() -> refundNotifyFacade.notifyHandle(refundNotifyDTO));
			}
		});		
    }
    
	/**
	 * 还款消息补偿
	 */
	public void compensationHandle() {
		Long beginTime = System.currentTimeMillis();
		List<String> batchNoList = refundNotifyRecordMapper.selectNeedHandleBatchNoList();
		log.info("还款消息补偿流程-重新发送待处理消息任务开启，待处理批次总数：{}", batchNoList.size());
		batchNoList.forEach(batchNo -> {
			RefundNotifyDTO refundNotifyDTO = new RefundNotifyDTO();
			refundNotifyDTO.setBatchNo(batchNo);
			refundNotifyFacade.notifyHandleCompensation(refundNotifyDTO);
		});
		log.info("还款消息补偿流程-重新发送待处理消息任务结束， 共耗时:{}mm", System.currentTimeMillis() - beginTime);
	}
	
	/**
	 * 订时清除已处理的消息
	 * 
	 * @param exceedDay
	 */
	public void clearHandledRecordByExceedDay(Integer exceedDay) {
		Long beginTime = System.currentTimeMillis();
		log.info("还款消息补偿流程-定时清除已处理的异常消息任务开启", System.currentTimeMillis());
		refundNotifyRecordMapper.deleteHandledRefundNotifyRecordByExceedDay(exceedDay);
		log.info("还款消息补偿流程-定时清除已处理的异常消息任务结束，共耗时：{}", System.currentTimeMillis() - beginTime);
	}

	/**
	 * 生成消息记录并入库
	 * 
	 * @param refundNotifyDTO
	 * @param refundStatus
	 * @param refundSource
	 * @param currentePeriod
	 * @param fromSubStatus
	 * @param toSubStatus
	 * @param isProjectHistoryOverdue
	 * @param orgRequestNo
	 * @param failMessage
	 * 
	 * @return
	 */
	private String createRefundNotifyRecord(RefundNotifyDTO refundNotifyDTO, Byte refundStatus, Byte refundSource, Integer currentePeriod,
			Integer fromSubStatus, Integer toSubStatus, Boolean isProjectHistoryOverdue, String orgRequestNo, String failMessage) {
		// 根据请求参数生成需要发送的消息列表
		List<RefundNotifyEnum> refundNotifyEnumList = bulidRefundNotifyEnumList(refundNotifyDTO, refundStatus,
				refundSource, currentePeriod, fromSubStatus, toSubStatus, isProjectHistoryOverdue);
		
		// 还款消息列表为空，直接返回
		if (null == refundNotifyEnumList || refundNotifyEnumList.size() == 0) {
			return null;
		}
		
		String batchNo = snowflakeIdWorker.nextId() + "";
		
		log.info("还款消息处理流程，BatchNo:{}, RefundNotifyEnum:{}", batchNo, refundNotifyEnumList);
		
		// 构建消息实体
		generateRefundNotifyRecordList(refundNotifyEnumList, refundNotifyDTO, refundSource, batchNo, refundStatus,
				currentePeriod, fromSubStatus, toSubStatus, orgRequestNo, failMessage);
		log.info("还款消息处理流程，生成消息记录完成，BatchNo:{}", batchNo);
		
		return batchNo;
	}
	
	/**
	 * 根据请求参数构建需要发送的消息列表
	 * 
	 * @param refundNotifyDTO
	 * @param refundStatus
	 *            还款状态 详见RefundNotifyRefundStatusEnum
	 * @param refundSource
	 *            还款来源 详见RefundNotifyRefundSourceEnum
	 * @param currentPeriod
	 *            当期期数
	 * @param fromSubStatus
	 * @param toSubStatus
	 * @param isProjectHistoryOverdue
	 *            标的历史是否有逾期，用于判断是否需要活动红包通知
	 * @return
	 */
	private List<RefundNotifyEnum> bulidRefundNotifyEnumList(RefundNotifyDTO refundNotifyDTO, Byte refundStatus,
			Byte refundSource, Integer currentPeriod, Integer fromSubStatus, Integer toSubStatus,
			Boolean isProjectHistoryOverdue) {
		
		Project project = refundNotifyDTO.getProject();
		RefundOrder refundOrder = refundNotifyDTO.getRefundOrder();
		
		List<RefundNotifyEnum> refundNotifyEnumList = Lists.newArrayList();
		
		ProjectSubStatusEnum fromSubStatusEnum = ProjectSubStatusEnum.enumOf(fromSubStatus);
		ProjectSubStatusEnum toSubStatusEnum = ProjectSubStatusEnum.enumOf(toSubStatus);

		Boolean isUpdateRepaymentPlan = false; // 是否更新还款计划(用户还款、代还)
		Boolean isOnlyUpdateInvestorPlan = false; // 是否只更新回款计划（担保）
		Boolean isUpdateProjectStatus = false; // 是否更新项目状态
		Boolean isProjectOverdue = false; // 是否标的逾期（包含坏帐）
		Boolean isProjectFinish = false; // 是否标的结清

		Boolean isR360 = ProjectFromSourceEnum.R360.getType().equals(project.getFromSource());
		Boolean isCardNiu = ProjectTypeEnum.CARD_NIU_LOAN.getValue().equals(project.getType()) && ProjectFromSourceEnum.CARD_NIU.getType().equals(project.getFromSource());
		Boolean isOrg = ProjectFromSourceEnum.ORG_SPEEDLOAN_NEW.getType().equals(project.getFromSource());
		Boolean isExchangeProject = project.getIsExchangeProject() == 1 || project.getIsExchangeProject() == 3;

		// 还款订单不为空、且处理成功
		if (null != refundOrder && RefundOrderStatusEnum.HANDLED.getCode().equals(refundOrder.getStatus())) {
			if (RefundTradeTypeEnum.REPAYMENT.getTradeType().equals(refundOrder.getTradeType())
					|| RefundTradeTypeEnum.REPLACE.getTradeType().equals(refundOrder.getTradeType())) {
				isUpdateRepaymentPlan = true;
			} else {
				isOnlyUpdateInvestorPlan = true;
			}
		}
		if (fromSubStatusEnum != null && !fromSubStatusEnum.equals(toSubStatusEnum)) {
			isUpdateProjectStatus = true;
		}
		
		if (ProjectSubStatusEnum.REPAYING_OVERDUE.equals(toSubStatusEnum)
				|| ProjectSubStatusEnum.REPAYING_BAD.equals(toSubStatusEnum)) {
			isProjectOverdue = true;
		} else if (ProjectStatusEnum.FINISH.equals(toSubStatusEnum.getParentStatusEnum())) {
			isProjectFinish = true;
		}
		
		// 还款计划与回款计划
		if (isUpdateRepaymentPlan) {
			refundNotifyEnumList.add(RefundNotifyEnum.SHENDUN_REFUND_RESULT);
			refundNotifyEnumList.add(RefundNotifyEnum.TIANCHENG_BORROWER_REFUND);
			refundNotifyEnumList.add(RefundNotifyEnum.TIANCHENG_INVESTOR_RECEIVE);
			refundNotifyEnumList.add(RefundNotifyEnum.MESSAGE_INVESTOR_RECEIVE);
			refundNotifyEnumList.add(RefundNotifyEnum.ACTIVITY_PRIZE_INVEST_RATE);
			refundNotifyEnumList.add(RefundNotifyEnum.ACTIVITY_EVENT_INVEST_RETURN_AMOUNT);
			refundNotifyEnumList.add(RefundNotifyEnum.ACTIVITY_RAISE_RATE);
			
			// 用户还款才发消息通知用户
			if (RefundTradeTypeEnum.REPAYMENT.getTradeType().equals(refundOrder.getTradeType())) {
				refundNotifyEnumList.add(RefundNotifyEnum.MESSAGE_BORROWER_REFUND);
			}
			// 判断是否进入逾期
			if (!isProjectHistoryOverdue) {
				// 借款返现红包借款人首次正常还款时返还，即第一期还款时
				if (null != currentPeriod && 1 == currentPeriod) {
					refundNotifyEnumList.add(RefundNotifyEnum.ACTIVITY_PRIZE_LOAN_RETURN_CASH);
				}
				refundNotifyEnumList.add(RefundNotifyEnum.ACTIVITY_PRIZE_INTEREST_DISCOUNT);
			}
			if (isR360) {
				refundNotifyEnumList.add(RefundNotifyEnum.R360_REFUND_RESULT);
				refundNotifyEnumList.add(RefundNotifyEnum.R360_REFUND_PLAN_CHANGE);
			}
			if (isCardNiu) {
				refundNotifyEnumList.add(RefundNotifyEnum.CARDNIU_REFUND_RESULT);
			}
			if (isOrg) {
				refundNotifyEnumList.add(RefundNotifyEnum.ORG_REFUND_RESULT);
				refundNotifyEnumList.add(RefundNotifyEnum.ORG_REFUND_PLAN_CHANGE);
			}
		} else if (isOnlyUpdateInvestorPlan) {
			refundNotifyEnumList.add(RefundNotifyEnum.TIANCHENG_INVESTOR_RECEIVE);
			refundNotifyEnumList.add(RefundNotifyEnum.MESSAGE_INVESTOR_RECEIVE);
			refundNotifyEnumList.add(RefundNotifyEnum.ACTIVITY_PRIZE_INVEST_RATE);
			refundNotifyEnumList.add(RefundNotifyEnum.ACTIVITY_EVENT_INVEST_RETURN_AMOUNT);
			refundNotifyEnumList.add(RefundNotifyEnum.ACTIVITY_RAISE_RATE);
		}
		
		// 状态变更
		if (isUpdateProjectStatus) {
			refundNotifyEnumList.add(RefundNotifyEnum.ACTIVITY_EVENT_PROJECT_STATUS_CHANGE);
			refundNotifyEnumList.add(RefundNotifyEnum.TIANCHENG_PROJECT_STATUS);
			
			// 是否更新至标的逾期
			if (isProjectOverdue) {
				refundNotifyEnumList.add(RefundNotifyEnum.ACTIVITY_PRIZE_BACKED);				
			}
			
			// 是否更新至标的结清
			if (isProjectFinish) {
				refundNotifyEnumList.add(RefundNotifyEnum.ACTIVITY_EVENT_AVA_AMOUNT_CHANGE);
				if (isExchangeProject) {
					refundNotifyEnumList.add(RefundNotifyEnum.ACTIVITY_EXCHANGE_RETURN_CASH);
				}
			}
			
			if (isR360) {
				refundNotifyEnumList.add(RefundNotifyEnum.R360_PROJECT_STATUS_CHANGE);
			}
			if (isCardNiu) {
				refundNotifyEnumList.add(RefundNotifyEnum.CARDNIU_PROJECT_STATUS_CHANGE);
			}
			if (isOrg) {
				refundNotifyEnumList.add(RefundNotifyEnum.ORG_PROJECT_STATUS_CHANGE);
			}
		}
		
		// 逾期通知
		if (isProjectOverdue) {
			refundNotifyEnumList.add(RefundNotifyEnum.ACTIVITY_EVENT_PROJECT_OVERDUE);
			refundNotifyEnumList.add(RefundNotifyEnum.SHENDUN_PROJECT_OVERDUE);
			refundNotifyEnumList.add(RefundNotifyEnum.TIANCHENG_PROJECT_OVERDUE);
			refundNotifyEnumList.add(RefundNotifyEnum.USER_BLACK_LIST);
		}
		
		// 还款失败，如果非系统发起需要发送消息通知
		if (RefundNotifyRefundStatusEnum.REPAPYMENT_FAIL.getStatus().equals(refundStatus)
				&& (RefundNotifyRefundSourceEnum.APP.getCode().equals(refundSource)
						|| RefundNotifyRefundSourceEnum.THIRD_ORG.getCode().equals(refundSource))) {
			if (isR360) {
				refundNotifyEnumList.add(RefundNotifyEnum.R360_REFUND_RESULT);
			}
			if (isCardNiu) {
				refundNotifyEnumList.add(RefundNotifyEnum.CARDNIU_REFUND_RESULT);
			}
			if (isOrg) {
				refundNotifyEnumList.add(RefundNotifyEnum.ORG_REFUND_RESULT);
			}

		}
		
		return refundNotifyEnumList;
	}
	
	/**
	 * 
	 * 根据枚举列表构建消息列表
	 * 
	 * @param refundNotifyEnumList
	 *            消息枚举列表
	 * @param refundNotifyDTO
	 *            消息请求参数封装
	 * @param refundSource
	 *            发起来源 详见:RefundNotifyRefundSourceEnum
	 * @param batchNo
	 * @param refundStatus
	 * @param currentPeriod
	 * @param fromSubStatus
	 * @param toSubStatus
	 * @param orgRequestNo
	 * @param failMessage
	 * 
	 * @return
	 */
	private void generateRefundNotifyRecordList(List<RefundNotifyEnum> refundNotifyEnumList,
			RefundNotifyDTO refundNotifyDTO, Byte refundSource, String batchNo, Byte refundStatus, Integer currentPeriod, Integer fromSubStatus,
			Integer toSubStatus, String orgRequestNo, String failMessage) {
		Project project = refundNotifyDTO.getProject();
		RefundOrder refundOrder = refundNotifyDTO.getRefundOrder();
		
		// 关联的投资订单
		List<ProjectInvestOrder> projectInvestOrderList = null;
		
		for (RefundNotifyEnum refundNotifyEnum : refundNotifyEnumList) {
			RefundNotifyRecord refundNotifyRecord = new RefundNotifyRecord();
			refundNotifyRecord.setBatchNo(batchNo);
			refundNotifyRecord.setProjectId(project.getProjectId());
			refundNotifyRecord.setRefundSource(refundSource);
			refundNotifyRecord.setRefundStatus(refundStatus);
			refundNotifyRecord.setCurrentPeriod(currentPeriod);
			refundNotifyRecord.setNotifyType(refundNotifyEnum.getType());
			refundNotifyRecord.setFromSubStatus(fromSubStatus);
			refundNotifyRecord.setToSubStatus(toSubStatus);
			refundNotifyRecord.setRetryNum(0);
			refundNotifyRecord.setRefundMessage(failMessage);
			refundNotifyRecord.setHandleStatus(RefundNotifyHandleStatusEnum.HANDLE_WAIT.getStatus());
			refundNotifyRecord.setCreateTime(new Date());
			refundNotifyRecord.setUpdateTime(new Date());
			
			// 借新还旧的暂时不返现，标记一条件正常状态以处的数据，避免系统处理
			if (RefundNotifyEnum.ACTIVITY_EXCHANGE_RETURN_CASH.equals(refundNotifyEnum)) {
				refundNotifyRecord.setHandleStatus((byte) 99);
			}
			
			// 还款订单信息
			if (null != refundOrder) {
				refundNotifyRecord.setRefundOrderId(refundOrder.getId());
				refundNotifyRecord.setOrgRequestNo(refundOrder.getOrgRequestNo());
			} else {
				refundNotifyRecord.setOrgRequestNo(orgRequestNo);
			}

			// 借款返现红包与借款利息折扣消息，需要判断标的是否关联红包
			if (RefundNotifyEnum.ACTIVITY_PRIZE_LOAN_RETURN_CASH.equals(refundNotifyEnum) ||
					RefundNotifyEnum.ACTIVITY_PRIZE_INTEREST_DISCOUNT.equals(refundNotifyEnum)) {
				if (null == project.getPrizeId() || project.getPrizeId() <= 0) {
					continue;
				}
			}
			
			// 天称投资回款数据回流、投资人回款消息以投资订单维度
			if (RefundNotifyEnum.TIANCHENG_INVESTOR_RECEIVE.equals(refundNotifyEnum)
					|| RefundNotifyEnum.MESSAGE_INVESTOR_RECEIVE.equals(refundNotifyEnum)) {
				if (CollectionUtils.isEmpty(projectInvestOrderList)) {
					projectInvestOrderList = projectInvestOrderMapper.selectInvestedList(project.getProjectId());
				}
				for (ProjectInvestOrder projectInvestOrder : projectInvestOrderList) {
					refundNotifyRecord.setId(snowflakeIdWorker.nextId());
					refundNotifyRecord.setInvestOrderId(projectInvestOrder.getId());
					refundNotifyRecordMapper.insertSelective(refundNotifyRecord);
				}
			}
			// 投资加息红包，以投资订单与期数维度
			else if (RefundNotifyEnum.ACTIVITY_PRIZE_INVEST_RATE.equals(refundNotifyEnum)) {
				if (CollectionUtils.isEmpty(projectInvestOrderList)) {
					projectInvestOrderList = projectInvestOrderMapper.selectInvestedList(project.getProjectId());
				}
				// 本次还款期数列表
				Set<Integer> peroids = bulidRefundPeroids(refundNotifyDTO.getRefundOrderDetailBizList());
				
				// 按投资订单与期数两个维度生成消息记录
				for (ProjectInvestOrder projectInvestOrder : projectInvestOrderList) {
					if (null == projectInvestOrder.getPrizeId() || projectInvestOrder.getPrizeId() <= 0 || null == projectInvestOrder.getPrizeTypteId()
							|| !UserPrizeTypeIdEnum.INVESTMENT_RAISE_INTEREST_RATES.getPrizeType().equals(projectInvestOrder.getPrizeTypteId())) {
						continue;
					}
					for (Integer period : peroids) {
						refundNotifyRecord.setId(snowflakeIdWorker.nextId());
						refundNotifyRecord.setInvestOrderId(projectInvestOrder.getId());
						refundNotifyRecord.setCurrentPeriod(period);
						refundNotifyRecordMapper.insertSelective(refundNotifyRecord);
					}
				}
			}
			// 运营投资加息活动（5.5.5增加智能投逻辑判断）
			else if (RefundNotifyEnum.ACTIVITY_RAISE_RATE.equals(refundNotifyEnum)) {
				if (null == project.getActivityRaiseRate() || project.getActivityRaiseRate().compareTo(BigDecimal.ZERO) <= 0) {
					Long packageId = projectPackageDetailMapperExt.selectPackageIdByProjectId(project.getProjectId());
					if (null == packageId) {
						continue;
					}
					ProjectPackage projectPackage = projectPackageMapperExt.selectByPrimaryKey(packageId);
					if (null == projectPackage || null == projectPackage.getActivityRaiseRate() || projectPackage.getActivityRaiseRate().compareTo(BigDecimal.ZERO) <= 0) {
						continue;
					}
				}
				
				if (CollectionUtils.isEmpty(projectInvestOrderList)) {
					projectInvestOrderList = projectInvestOrderMapper.selectInvestedList(project.getProjectId());
				}
				// 本次还款期数列表
				Set<Integer> peroids = bulidRefundPeroids(refundNotifyDTO.getRefundOrderDetailBizList());
				
				// 按投资订单与期数两个维度生成消息记录
				for (ProjectInvestOrder projectInvestOrder : projectInvestOrderList) {
					for (Integer period : peroids) {
						refundNotifyRecord.setId(snowflakeIdWorker.nextId());
						refundNotifyRecord.setInvestOrderId(projectInvestOrder.getId());
						refundNotifyRecord.setCurrentPeriod(period);
						refundNotifyRecordMapper.insertSelective(refundNotifyRecord);
					}
				}
			}
			else if (RefundNotifyEnum.ACTIVITY_EVENT_INVEST_RETURN_AMOUNT.equals(refundNotifyEnum)) {
				if (CollectionUtils.isEmpty(projectInvestOrderList)) {
					projectInvestOrderList = projectInvestOrderMapper.selectInvestedList(project.getProjectId());
				}
				
				// 按投资订单维度生成消息记录
				for (ProjectInvestOrder projectInvestOrder : projectInvestOrderList) {
					refundNotifyRecord.setId(snowflakeIdWorker.nextId());
					refundNotifyRecord.setInvestOrderId(projectInvestOrder.getId());
					refundNotifyRecordMapper.insertSelective(refundNotifyRecord);
				}				
			}
			else {
				refundNotifyRecord.setId(snowflakeIdWorker.nextId());
				refundNotifyRecordMapper.insertSelective(refundNotifyRecord);
			}
		}
	}

	/**
	 * 转化成还款通知中的还款来源
	 * <p/>
	 * <li>1、考虑代扣交易来源</li>
	 * <li>2、考虑还款订单来源</li>
	 * <li>3、考虑还款交易来源</li>
	 * <li>4、以上都为空时，默认为系统自动</li>
	 * 
	 * @param withholdTradeSource
	 *            代扣交易来源
	 * @param refundTradeSource
	 *            还款交易来源
	 * @param refundOrder
	 *            还款订单
	 * @return
	 */
	private RefundNotifyRefundSourceEnum transformRefundSource4WithholdAndRefund(Byte withholdTradeSource, Byte refundTradeSource, RefundOrder refundOrder) {
		RefundNotifyRefundSourceEnum refundNotifyRefundSourceEnum = null;
		
		if (null != withholdTradeSource) {
			if (RefundWithholdRequestDTO.WithHoldTradeSourceEnum.JOB.getValue().equals(withholdTradeSource)
					|| RefundWithholdRequestDTO.WithHoldTradeSourceEnum.SHENDUN.getValue().equals(withholdTradeSource)) {
				refundNotifyRefundSourceEnum = RefundNotifyRefundSourceEnum.SYSTEM;
			} else {
				refundNotifyRefundSourceEnum = RefundNotifyRefundSourceEnum.THIRD_ORG;
			}
		}
		
		if (null == refundNotifyRefundSourceEnum && null != refundOrder) {
			if (OrderTradeSourceEnum.WITHHOLD.getTradeSource().equals(refundOrder.getTradeSource())) {
				RefundWithholdOrder refundWithholdOrder = refundWithholdOrderMapper.selectByRefundOrderId(refundOrder.getId());
				if (refundWithholdOrder != null && (RefundWithholdRequestDTO.WithHoldTradeSourceEnum.JOB.getValue().equals(refundWithholdOrder.getTradeSource())
						|| RefundWithholdRequestDTO.WithHoldTradeSourceEnum.SHENDUN.getValue().equals(refundWithholdOrder.getTradeSource()))) {
					refundNotifyRefundSourceEnum = RefundNotifyRefundSourceEnum.SYSTEM;
				} else {
					refundNotifyRefundSourceEnum = RefundNotifyRefundSourceEnum.THIRD_ORG;
				}
			} else if (OrderTradeSourceEnum.APP.getTradeSource().equals(refundOrder.getTradeSource())) {
				refundNotifyRefundSourceEnum = RefundNotifyRefundSourceEnum.APP;
			} else {
				refundNotifyRefundSourceEnum = RefundNotifyRefundSourceEnum.SYSTEM;
			}
		}
		
		if (null == refundNotifyRefundSourceEnum && null != refundTradeSource) {
			if (OrderTradeSourceEnum.APP.getTradeSource().equals(refundTradeSource)) {
				refundNotifyRefundSourceEnum = RefundNotifyRefundSourceEnum.APP;
			} else {
				refundNotifyRefundSourceEnum = RefundNotifyRefundSourceEnum.SYSTEM;
			}
		}
		
		if (null == refundNotifyRefundSourceEnum) {
			refundNotifyRefundSourceEnum = RefundNotifyRefundSourceEnum.SYSTEM;
		}
		
		return refundNotifyRefundSourceEnum;
	}
	
	/**
	 * 构建本次还款期数
	 * 
	 * @param refundOrderDetailBizList
	 * @return
	 */
	private Set<Integer> bulidRefundPeroids(List<RefundOrderDetailBiz> refundOrderDetailBizList) {
		Set<Integer> peroids = Sets.newHashSet();
		for (RefundOrderDetailBiz refundOrderDetailBiz : refundOrderDetailBizList) {
			if (refundOrderDetailBiz.getAmount().compareTo(BigDecimal.ZERO) <= 0
					|| (!BusinessTypeEnum.REPAYMENT.name().equals(refundOrderDetailBiz.getBizType())
							&& !BusinessTypeEnum.COMPENSATORY.name().equals(refundOrderDetailBiz.getBizType()))) {
				continue;
			}
			peroids.add(refundOrderDetailBiz.getCurrentPeriod());
		}
		return peroids;
	}	
}